/**
 *  @file
 *  @brief   Hexa8SRI单元
 *  @author  xiashijun
 *  @date    2025.03.11
 *  @version v1.0
 *  @par Copyright(c):  ShenGong  Simulation corporation
 */

#pragma once
#include "Utility/Algebra/Matrix.h"
#include "Utility/Algebra/Point.h"

#include "DataStructure/Common/Out.h"
#include "DataStructure/Common/Real.h"
#include "DataStructure/Input/Property/PSOLIDData.h"

#include "SGFem/Integration/IntegrationFormula/Gauss3D2X2X2P.h"
#include "SGFem/Integration/ShapeFunction/Hexa8NodeShpFunc.h"
#include "SGFem/Integration/ShapeFunction/Hexa8NodeIncomShpFunc.h"
#include "../Interface/IElementCalculator.h"

using SG::DataStructure::Common::Real;

SG_FEMSOLVER_ELEMENT_NAMESPACE_OPEN
class ElementCalculator_DECLSPEC Hexa8SRIElementCalculator: public SG::FEMSolver::Element::IElementCalculator
{
public:
    Hexa8SRIElementCalculator() = default;
    virtual ~Hexa8SRIElementCalculator() = default;
    
    /**
     * @brief    单元中心点雅可比矩阵J0计算
     * @author   xiashijun
     * @date     2025.03.13
     *      
     * @param    [in] localCoord 单元节点坐标（单元坐标系）
     * @param    [out] invJ0  单元中心点雅可比矩阵逆矩阵
     * @param    [out] detJ0  单元中心点雅可比矩阵行列式
     */
    void CalcJ0Matrix (const SG::Algebra::Matrixd& localCoord, _OUT SG::Algebra::Matrixd& invJ0, _OUT Real& detJ0);

    /**
     * @brief    应变矩阵计算
     * @author   xiashijun
     * @date     2025.03.11
     *      
     * @param    [in] localCoord 单元节点坐标（单元坐标系）
     * @param    [in] iGauss 积分点索引
     * @param    [out] B 几何矩阵（单元坐标系）
     * @param    [out] detJ 雅可比矩阵的行列式
     */
    void CalcBMatrix (const SG::Algebra::Matrixd& localCoord, int iGauss, _OUT SG::Algebra::Matrixd& B, _OUT Real& detJ);
    /**
     * @brief    非协调应变增强计算
     * @author   xiashijun
     * @date     2025.03.11
     *      
     * @param    [in] iGauss 积分点索引
     * @param    [in] invJ0 中心点雅可比矩阵的逆矩阵
     * @param    [in] detJ  积分点雅可比矩阵的行列式
     * @param    [in] detJ0 中心点雅可比矩阵的行列式
     * @param    [out] G 应变增强矩阵（单元坐标系）
     */
    void CalcGMatrix (int iGauss, const SG::Algebra::Matrixd invJ0, Real J0OverJ, _OUT SG::Algebra::Matrixd& G);
    /**
     * @brief    计算单元刚度矩阵（单元坐标系）
     * @author   xiashijun
     * @date     2025.03.11
     *      
     * @param    [in] localCoord 单元节点坐标（单元坐标系）
     * @param    [in] D  材料弹性矩阵（单元坐标系）
     * @param    [out] K 刚度矩阵（单元坐标系）
     */
    void ComputeStiffness (const SG::Algebra::Matrixd& localCoord,const SG::Algebra::Matrixd& D,_OUT SG::Algebra::Matrixd& K);
    /**
     * @brief    计算基于单元的应力应变坐标系（即 mCId = -2）变换矩阵
     * 
     * @param    [in] pointSet Basic 坐标系单元节点坐标
     * @param    [out] TS 基于单元的应力应变坐标系（即 mCId = -2）变换矩阵
     * @author   xiashijun
     * @date     2025.03.17
     */
    static void ComputeInternalCoordTrans (const SG::Algebra::PointArray& pointSet, _OUT SG::Algebra::Matrixd& TS);

    virtual void Initialize (SG::DataStructure::FEM::ElementTypes type) override;
    virtual void ComputeElementMatries (const SG::DBManager::DBServiceFactorySP dbServiceFactory) override;
    virtual void DataRecovery (const SG::DBManager::DBServiceFactorySP             dbServiceFactory,
        int                                                 subcaseId, 
        SG::DataStructure::Common::Real time,
        const std::vector<SG::DataStructure::Common::Real>& globalDisplacement) override {};
    virtual void ComputeStressStiffness (const SG::DBManager::DBServiceFactorySP dbServiceFactory, int staticSubId) override;

    static ElementCalculatorSP Create ()
    {
        return std::make_shared<Hexa8SRIElementCalculator> ();
    }
    
private:
    SG::DataStructure::FEM::ElementTypes m_type;
    SG::FEMSolver::Element::Gauss3D2X2X2P m_integCalc;
    SG::FEMSolver::Element::Hexa8NodeShpFunc m_shpFunc;
    // SG::FEMSolver::Element::Hexa8NodeShpFunc m_shpFunc_centor;
    SG::FEMSolver::Element::Hex8NodeIncomShpFunc m_shpFuncIncom;

};
SG_FEMSOLVER_ELEMENT_NAMESPACE_CLOSE